/*
 * @Author: Blake He
 * @Date: 2022-09-05 10:35:50
 * @Description: 七牛vite上传插件
 * @LastEditTime: 2023-08-23 13:40:22
 * @LastEditors: yuyang
 */

import glob from 'glob'
import chalk from 'chalk'
import path from 'path'
import fs from 'fs'
import { normalizePath } from 'vite'
import { v4 as uuid } from 'uuid'
import Qiniu from './qiniu'
import Reporter from './reporter'
import utils from './utils'

const removeDir = (dir) => {
  if (fs.existsSync(dir)) {
    const files = fs.readdirSync(dir)
    for (let i = 0; i < files.length; i++) {
      const newPath = path.join(dir, files[i])
      const stat = fs.statSync(newPath)
      if (stat.isDirectory()) {
        removeDir(newPath)
      } else {
        fs.unlinkSync(newPath)
      }
    }
    if (fs.existsSync(dir)) {
      fs.rmdirSync(dir)
    }
  }
}

const viteFunctionQiniuOss = async (openUpload, mode, outDir) => {
  const reporter = new Reporter('\n')
  const options = utils.getFileOptions()
  if (!openUpload) {
    reporter.stop()
    return
  }

  if (!utils.validateOptions(options)) {
    reporter.stop()
    return
  }

  const outDirPath = normalizePath(path.resolve(normalizePath(outDir)))
  const createOssOption: any = { ...options }
  const { accessKey, secretKey, production } = createOssOption
  const qiniu = new Qiniu({
    accessKey,
    secretKey,
    bucket: production.bucket,
    domain: production.domain
  })

  const files = await glob.sync(`${outDirPath}/**/*`, {
    strict: true,
    nodir: true,
    dot: true,
    ignore: ['**/**/*.html']
    // ignore: ['**/**/*.html', '**/images/**']
  })

  reporter.log = '=====qiniu oss 开始上传=====  \n'

  const startTime = new Date().getTime()
  const releaseFiles = files.map((item) => {
    return item.split(outDirPath)[1]
  })

  reporter.log = '=====正在获取历史数据=====  \n'

  // 获取文件日志
  const {
    uploadTime,
    prev: prevFiles = [],
    current: currentFiles = []
  } = await utils.getLogFile(createOssOption, qiniu)

  // 合并去重，提取最终要上传和删除的文件
  const { uploadFiles, deleteFiles } = utils.combineFiles(prevFiles, currentFiles, releaseFiles)

  reporter.log = `=====将上传 ${uploadFiles.length} 个文件=====`
  reporter.log = `=====将删除 ${deleteFiles.length} 个文件=====`

  let current = 0
  const uploadFileTasks = uploadFiles.map((filename, index) => {
    const localUrl = outDirPath + filename
    const uploadPath = createOssOption.uploadPath.replace(/\//g, '')
    const key = uploadPath + filename
    const id = uuid()
    const callback = (taskId: string, process: number) => {}
    // this.taskRunner.setProgress(taskId, process);
    return async () => {
      await qiniu.putFile(id, key, localUrl, {}, callback).then(() => {
        current += 1
        const percent = (current / uploadFiles.length) * 100
        reporter.log = `当前进度${percent.toFixed(2)}%`
      })
    }
  })

  // const deleteFileKeys = deleteFiles.map((filename, index) => {
  //     const qiniuPath =
  //         mode === 'sit' ? 'https://static.sit.whalepms.com/whalepms-h5' : 'https://static.whalepms.com/whalepms-h5'
  //     const key = qiniuPath + filename
  //     return async () => {
  //         await qiniu.batchDelete(key)
  //     }
  // })

  try {
    await utils.mapLimit(uploadFileTasks, createOssOption.batch, (task, next) => {
      const fn = async () => {
        try {
          const res = await task()
          next(null, res)
        } catch (err) {
          next(err)
        }
      }

      fn()
    })
  } catch (e) {
    console.error(chalk.bold.red('\n\n上传失败:'), e)
    // callback(e)
  }

  const duration = (new Date().getTime() - startTime) / 1000
  console.log(`=====上传完毕, cost ${duration.toFixed(2)}s`)

  reporter.text = '=====正在写入日志...\n'
  await utils.writeLogFile({ currentFiles, releaseFiles, qiniu, createOssOption })
  reporter.log = '=====日志记录完毕\n'

  reporter.succeed('===== \n')
  console.log(chalk.bold.green('==== 七牛CDN上传完毕 ==== \n'))

  console.log(chalk.bold.red('=====正在删除历史文件...\n'))
  await utils.deleteOldFiles({ createOssOption, deleteFiles, qiniu })
  console.log(chalk.bold.red('=====历史文件删除完毕\n'))

  // 移除打包文件下静态资源
  const assetsDirPath = path.resolve(__dirname, `${outDirPath}/assets`)
  const iconsDirPath = path.resolve(__dirname, `${outDirPath}/icons`)
  removeDir(assetsDirPath)
  removeDir(iconsDirPath)

  console.log(chalk.bold.green('==== 移除打包目录下静态资源assets、icons文件夹 ==== \n'))
}

export default viteFunctionQiniuOss
